package com.tianji.learning.task;

import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.learning.constants.LearningConstants;
import com.tianji.learning.constants.RedisConstants;
import com.tianji.learning.domain.po.PointsBoard;
import com.tianji.learning.domain.po.PointsBoardSeason;
import com.tianji.learning.domain.query.PointsBoardQuery;
import com.tianji.learning.service.IPointsBoardSeasonService;
import com.tianji.learning.service.IPointsBoardService;
import com.tianji.learning.service.impl.PointsBoardServiceImpl;
import com.tianji.learning.utils.TableInfoContext;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import io.swagger.models.auth.In;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.BoundZSetOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;

@Component
@RequiredArgsConstructor
public class PointsBoardPersistentTask {
    private final IPointsBoardService boardService;
    private final IPointsBoardSeasonService seasonService;
    private final StringRedisTemplate redisTemplate;

    /**
     * 创建历史积分排行榜 对应的表
     */
    @XxlJob("createBoardTable")
    public void createHistoryBoardTable() {
        // 1 定时创建上月的 积分排行榜 对应的表
        // 1.1 获取上月时间
        LocalDateTime time = LocalDateTime.now().minusMonths(1);
        // 1.2 根据上月时间，再赛季表中查询出对应的赛季id
        Integer seasonId = seasonService.querySeasonIdByTime(time);
        // 1.3 根据赛季id创建 历史积分排行榜表
        if (ObjectUtils.isEmpty(seasonId)) {
            return;
        }
        boardService.createPointsBoardTable(seasonId);
    }

    // 2 持久化 redis 中积分排行榜
    @XxlJob("savePointsBoard2DB")
    public void savePointsBoard2DB() {
        // 1 获取上月时间
        LocalDateTime time = LocalDateTime.now().minusMonths(1);
        // 2 计算动态表名
        // 2.1 查询赛季ID、拼接表名
        Integer seasonId = seasonService.querySeasonIdByTime(time);
        String tableName = LearningConstants.POINTS_BOARD_TABLE_PREFIX + seasonId;

        // 2.2 将表名存入ThreadLocal，当前线程任意处代码都能获取该值
        TableInfoContext.setTableName(tableName);

        // 3 查询redis中上月的积分排行榜数据
        // 3.1 拼接key
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + time.format(DateUtils.DATE_SUFFIX_FORMATTER);
        // 3.2 查询榜单数据 分片查询
        Integer index = XxlJobHelper.getShardIndex();// xxljob当前实例的分片序号
        Integer total = XxlJobHelper.getShardTotal();// xxljob总分片数量
        Integer pageNo = 1 + index;
        Integer pageSize = 4;

        // 查询上月积分排行榜
        while (true) {
            List<PointsBoard> boardList = boardService.queryLastMonthPointsBoard(key, pageNo, pageSize);
            if (ObjectUtils.isEmpty(boardList)) {
                break;
            }
            // 4 封装vo，将上月榜单数据 持久化到数据库
            for (PointsBoard pointsBoard : boardList) {
                pointsBoard.setId(pointsBoard.getRank().longValue());
            }
            boardService.saveBatch(boardList);
            pageNo += total;
        }

        // 5 清理ThreadLocal 防止内存溢出
        TableInfoContext.removeTableName();

    }

    // 3 清除redis zset中上月榜单数据
    @XxlJob("clearPointsBoardFromRedis")
    public void clearLastMonthPointsBoardFromRedis() throws InterruptedException {
        Thread.sleep(10000l);
        // 1 获取上月时间
        LocalDateTime time = LocalDateTime.now().minusMonths(1);
        // 2 拼接key
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + time.format(DateUtils.DATE_SUFFIX_FORMATTER);
        // 3 异步删除redis中数据
        redisTemplate.unlink(key);

    }


}
